home *** CD-ROM | disk | FTP | other *** search
- ' *** DIR.BAS ***
- '
- ' Fairchild Computer Services
- ' Route 5, Box 523-12
- ' Wills Point, TX 75169
- ' (903) 873-2114
- '
- '**************************** GENERAL NOTATIONS ***************************
- ' I wrote this program for several reasons:
- ' 1) To serve as a good example of how to use QuickBASIC's INTERRUPT and
- ' INTERRUPTX subroutines.
- ' 2) QuickBasic doesn't have any good 'directory-getting' functions.
- ' ('FILES' just doesn't cut it!).
- ' 3) To solicit comments on my coding, and use of interrupts.
- ' 4) Return a SMALL bit for all I've learned from the Shareware community.
- ' 5) Let people know I exist for possible business/idea networking.
- ' Enjoy!! -jmf
- '**************************************************************************
-
- '************************** COMMAND LINE CREATION *************************
- ' To make a quicklibrary: | | To make a makefile, create a file
- ' BC DIR/O/T/C:512; | | named: YOURFILE.MAK (where YOURFILE
- ' LINK DIR/EX/NOE/NOD:BRUN45.LIB | | is the file you wish to use). In it:
- ' DIR | or |
- ' NUL | | YOURFILE.BAS
- ' BCOM45.LIB+ | | DIR.BAS
- ' QB.LIB | |
- '**************************************************************************
-
- '************************** FUNCTION DECLARATIONS *************************
- '**************************************************************************
-
- '************************* SUBROUTINE DECLARATIONS ************************
- '**************************************************************************
-
- '******************* CONSTANT/INCLUDE FILE DECLARATIONS *******************
-
- ' $INCLUDE: 'DIR.INC' 'Use this for DIR.BAS declares, etc.
- ' $INCLUDE: 'QB.BI' 'Use this for interrupt calls
-
- '**************************************************************************
-
- '************************ DATABASE (TYPE) LAYOUTS *************************
- '**************************************************************************
-
- '**************** DECLARE GLOBAL (COMMON) SHARED VARIABLES ****************
- '**************************************************************************
-
- '********************* DECLARE LOCAL SHARED VARIABLES *********************
-
- DIM SHARED DTAOff% 'Holds DTA segment offset address
-
- '**************************************************************************
-
- '**************************** CREATE VARIABLES ****************************
- '**************************************************************************
-
- '*************************** DATA DECLARATIONS ****************************
- '**************************************************************************
-
- '************************* MAIN SUBROUTINE CALLS **************************
- '**************************************************************************
-
- '*************************** DATA DECLARATIONS ****************************
- '**************************************************************************
-
- '***************************** EXIT ROUTINES ******************************
- '**************************************************************************
-
- FUNCTION ConvertDate$ (DateIn&)
-
- DirMon$ = MaskIt$(LTRIM$(STR$(INT(DateIn& / 32) AND 15)), 2, "Z")
- DirDay$ = MaskIt$(LTRIM$(STR$(DateIn& AND 31)), 2, "Z")
- DirYr$ = MaskIt$(LTRIM$(STR$(INT(DateIn& / 512) + 1980)), 2, "Z")
-
- ConvertDate$ = DirMon$ + "/" + DirDay$ + "/" + DirYr$
-
- END FUNCTION
-
- FUNCTION ConvertSize$ (SizeIn&)
-
- ConvertSize$ = MaskIt$(LTRIM$(STR$(SizeIn&)), 9, "R")
-
- END FUNCTION
-
- FUNCTION ConvertTime$ (TimeIn&)
-
- DirHour% = INT(TimeIn& / 2048)
- SELECT CASE DirHour%
- CASE 0
- DirHour% = 12
- AmPm$ = "a"
- CASE IS < 12
- AmPm$ = "a"
- CASE 12
- AmPm$ = "p"
- CASE ELSE
- DirHour% = DirHour% - 12
- AmPm$ = "p"
- END SELECT
- DirHour$ = MaskIt$(LTRIM$(STR$(DirHour%)), 2, "Z")
- DirMins$ = MaskIt$(LTRIM$(STR$(INT(TimeIn& / 32) AND 63)), 2, "Z")
-
- ConvertTime$ = DirHour$ + ":" + DirMins$ + AmPm$
-
- END FUNCTION
-
- FUNCTION CurrentDevice$
-
- InRegs.AX = &H1900 'AH=19 (function) [gets default drive]
- CALL INTERRUPT(&H21, InRegs, OutRegs) 'Interrupt 21
- DefaultDrive% = OutRegs.AX AND 255 '0=A, 1=B, etc.
-
- CurrentDevice$ = MID$(alphabet$, DefaultDrive% + 1, 1) + ":"
-
- END FUNCTION
-
- FUNCTION CurrentDir$
-
- ' This function will use the Dir$ function to determine the current
- ' DEVICE:\DIRECTORY on the default device.
-
- t$ = null$ 'Initialize temp variable
- DirPath$ = SPACE$(255) 'Set up buffer area
- InRegsX.AX = &H4700 'AH=47 (function) [gets current path]
- InRegsX.DX = Lit0% 'Input device designation
- InRegsX.DS = VARSEG(DirPath$) 'Buffer segment address
- InRegsX.SI = SADD(DirPath$) 'Buffer offset address
- CALL INTERRUPTX(&H21, InRegsX, OutRegsX) 'Interrupt 21
- ErrorFlag% = OutRegsX.FLAGS AND 1 '0=good, 1=bad code
- ErrorCode% = OutRegsX.AX 'AX contains error when FLAGS and 1=1
- IF ErrorFlag% THEN 'We got an error?
- t$ = DirError$(ErrorCode%) ' yep, return as Dir$ call string
- GOTO ExitCurrentDir ' and get outta here
- END IF
-
- DirPath$ = LEFT$(DirPath$, INSTR(DirPath$, CHR$(0)) - 1)
- t$ = CurrentDevice$ + "\" + DirPath$
-
- GOTO ExitCurrentDir
-
- ExitCurrentDir:
- CurrentDir$ = t$ 'Return correct DEVICE:\DIRECTORY val
- END FUNCTION
-
- FUNCTION Dir$ (file$)
-
- ' This function is called using: variable$ = Dir$(filespec$)
- ' The first filename matching filespec$ will be returned. Subsequent
- ' calls should pass a null (ex: variable$ = Dir$("")) string for more
- ' filenames matching original filespec call. When no more matches are
- ' found, null is returned. To reset, use a new filespec$.
- ' - The following is the breakdown of the output from Dir$():
- ' DirRecord.EntryName (STRING * 12)
- ' DirRecord.EntrySize (LONG - can be converted using DirConvert)
- ' DirRecord.EntryDate (LONG - can be converted using DirConvert)
- ' DirRecord.EntryTime (LONG - can be converted using DirConvert)
- ' DirRecord.ReadOnlyFlag (INTEGER - True/False)
- ' DirRecord.HiddenFlag (INTEGER - True/False)
- ' DirRecord.SystemFlag (INTEGER - True/False)
- ' DirRecord.ArchiveFlag (INTEGER - True/False)
- ' DirRecord.DirectoryFlag (INTEGER - True/False)
-
- InRegsX.AX = &H2F00 'AH=2F (function) [gets DTA address]
- CALL INTERRUPTX(&H21, InRegsX, OutRegsX) 'Interrupt 21
- DTASeg% = OutRegsX.ES 'Gets DTA segment address
- DTAOff% = OutRegsX.BX 'DTA offset address
- IF file$ <> "" THEN 'Check if first lookup
- file$ = file$ + CHR$(0) 'file$ needs a terminator
- InRegsX.AX = &H4E00 'AH=4E (function) [get 1st dir entry]
- InRegsX.CX = &HFFFF 'Set for all attributes
- InRegsX.DS = VARSEG(file$) 'Segment address of filename
- InRegsX.DX = SADD(file$) 'Filename offset
- CALL INTERRUPTX(&H21, InRegsX, OutRegsX) 'Interrupt 21
- DirRecord.ErrorFlag = OutRegsX.FLAGS AND 1 '0=good, 1=bad code
- ErrorCode% = OutRegsX.AX 'AX contains error when FLAGS and 1=1
- IF DirRecord.ErrorFlag THEN 'We got an error?
- t$ = DirError$(ErrorCode%) ' yep, return as Dir$ call string
- GOTO ExitDir ' and get outta here
- END IF
- ELSE 'Must be subsequent lookup...
- InRegsX.AX = &H4F00 'AH=4F (function) [get next dir entry]
- CALL INTERRUPTX(&H21, InRegsX, OutRegsX) 'Interrupt 21
- DirRecord.ErrorFlag = OutRegsX.FLAGS AND 1 '0=good, 1=bad code
- ErrorCode% = OutRegsX.AX 'AX contains error when FLAGS and 1=1
- IF DirRecord.ErrorFlag THEN 'We got an error?
- t$ = DirError$(ErrorCode%) ' yep, return as Dir$ call string
- GOTO ExitDir ' and get outta here
- END IF
- END IF
- DEF SEG = DTASeg% 'Use DTA segment address
- c% = 30 'Init filename bit counter
- t$ = "" 'Init tempname holder
- DO 'Start loop
- t$ = t$ + CHR$(DTABit%(c%)) 'Get next bit & add
- c% = c% + 1 'Increment bit counter
- LOOP UNTIL DTABit%(c%) = 0 'Keep goin til we hit end ASCII '0'
- ' Can't mask following in case dir name is integer value (won't sort!)
- DirRecord.EntryName = LEFT$(t$ + SPACE$(12), 12)
- DirRecord.EntryTime = DTABit%(22) + DTABit%(23) * 256&
- DirRecord.EntryDate = DTABit%(24) + DTABit%(25) * 256&
- DirRecord.EntrySize = DTABit%(26) + DTABit%(27) * 256& + DTABit%(28) * 65536
- Attr% = DTABit%(21) 'Interpret attribute bit
- DirRecord.ReadOnlyFlag = Attr% AND 1 'File read-only bit set? (T/F)
- DirRecord.HiddenFlag = Attr% AND 2 'File hidden bit set? (T/F)
- DirRecord.SystemFlag = Attr% AND 4 'File system bit set? (T/F)
- DirRecord.ArchiveFlag = Attr% AND 8 'File archive bit set? (T/F)
- DirRecord.DirectoryFlag = Attr% AND 16'File directory bit set? (T/F)
- DEF SEG 'Back to BASIC segment
-
- GOTO ExitDir
-
- ExitDir:
- Dir$ = t$
- END FUNCTION
-
- FUNCTION DirCount% (file$)
-
- ' This function will return the number of valid directory entries
- ' matching file$.
-
- c% = 0 'Initialize counter
- t$ = Dir$(file$) 'Do first call for match
- IF t$ <> null$ THEN 'Find one??
- DO 'Yes, begin search loop
- c% = c% + 1 'Increment counter
- t$ = Dir$(null$) 'Get next match
- LOOP UNTIL t$ = null$ ' until no more matches found
- END IF
-
- DirCount% = c% 'Return directory entry count
-
- END FUNCTION
-
- FUNCTION DirError$ (Code%)
-
- SELECT CASE Code% 'Check AX register for error
- CASE 3 '3 means path not found
- t$ = "Wrong Path " 'tell em
- DirRecord.ErrorDesc = t$ ' and error description
- CASE 15 '15 means bad device (not found)
- t$ = "No Device " 'tell em
- DirRecord.ErrorDesc = t$ ' and error description
- CASE 18 '18 means no more files found
- t$ = "" 'tell em
- DirRecord.ErrorDesc = "NoMoreFound " ' and error description
- CASE ELSE 'Don't know any others
- t$ = "UnknownError" ' so, let em know
- DirRecord.ErrorDesc = t$ ' and error description
- END SELECT
- DirRecord.EntryName = t$ 'Pass back entry name as error
-
- DirError$ = t$ ' ...and finally, return the call val
-
- END FUNCTION
-
- FUNCTION DTABit% (BitNumber%)
-
- DTABit% = PEEK(DTAOff% + BitNumber%)
-
- END FUNCTION
-
- FUNCTION MaskIt$ (text$, length%, edits$)
-
- ' MaskIt$ is a simple function that will edit (mask) an input string. It
- ' can be used to add leading zeroes, justify text or numbers, etc. If you
- ' wish to edit numeric type data, you will need to convert it into text$
- ' before using this function (use STR$).
- '
- ' edits$ includes a combination of the following:
- ' C = Compress (extract all spaces)
- ' L = Left justify
- ' R = Right justify
- ' T = Trim leading and trailing spaces
- ' Z = Add leading zeros
- ' , = Add commas to numeric string
-
- edits$ = UCASE$(edits$)
- blank$ = SPACE$(1)
- comma$ = ","
- numeric$ = "0123456789"
- slash$ = "/"
- IF INSTR(edits$, "T") THEN text$ = LTRIM$(RTRIM$(text$))
- l% = LEN(text$)
- IF INSTR(edits$, "C") OR INSTR(edits$, ",") THEN
- c$ = ""
- c% = 1
- DO
- IF MID$(text$, c%, 1) <> blank$ THEN c$ = c$ + MID$(text$, c%, 1)
- c% = c% + 1
- LOOP UNTIL c% > l%
- text$ = c$
- END IF
- IF INSTR(edits$, "L") THEN
- text$ = LEFT$(text$ + SPACE$(length%), length%)
- ELSE
- IF INSTR(edits$, "R") THEN
- text$ = RIGHT$(SPACE$(length%) + text$, length%)
- END IF
- END IF
- IF INSTR(edits$, "Z") THEN text$ = RIGHT$(STRING$(length%, 48) + text$, length%)
- IF INSTR(edits$, ",") THEN
- SELECT CASE LEN(text$) 'Evaluate string length
- CASE IS < 4 '3 or less?
- CASE ELSE 'Otherwise...
- t$ = text$ 'Save text$ to temp work variable
- c$ = "" 'Initialize temp string variable
- DO 'Begin loop
- lt% = LEN(t$) 'Save string length to temp variable
- c$ = c$ + LEFT$(t$, 1) 'Add another digit
- t$ = RIGHT$(t$, lt% - 1) 'Elim digit from string
- IF lt% MOD 3 = 1 THEN 'Divisible by 3?
- IF lt% > 1 THEN c$ = c$ + "," 'Yes, add comma
- END IF 'End division check
- LOOP WHILE lt% > 1 'End loop if last digit
- END SELECT
- text$ = c$
- END IF
-
- ExitMaskIt:
-
- MaskIt$ = text$
-
- END FUNCTION
-
-